use std::borrow::Cow;

use chrono::{NaiveDate, NaiveDateTime};
use serde_json::Value;

use crate::prelude::DataType;
use numfmt::Formatter;
#[cfg(feature = "ssr")]
pub mod date;
#[cfg(feature = "ssr")]
pub mod date_parser;

pub fn json_value_to_string(jval: &Value) -> String {
    match jval {
        Value::String(s) => s.clone(),
        Value::Number(n) => n.to_string(),
        Value::Bool(b) => b.to_string(),
        Value::Null => "".to_string(),
        Value::Array(arr) => {
            let mut s = "[ ".to_string();
            for (i, v) in arr.iter().enumerate() {
                if i > 0 {
                    s.push_str(", ");
                }
                s.push_str(&json_value_to_string(v));
            }
            s.push_str(" ]");
            s
        }
        Value::Object(obj) => {
            let mut s = "{ ".to_string();
            for (i, (k, v)) in obj.iter().enumerate() {
                if i > 0 {
                    s.push_str(", ");
                }
                s.push_str(&format!("\"{}\": {}", k, json_value_to_string(v)));
            }
            s.push_str(" }");
            s
        }
    }
}
pub fn format_json_value_with_space(
    dt: Option<&DataType>,
    fmt: Option<&str>,
    value: &Value,
) -> (String, usize) {
    let mut sval = format_json_value(dt, fmt, value);
    let is_num_end=sval.as_bytes().last().map(|v| *v==b'%' || v.is_ascii_digit()).unwrap_or(false);
    if is_num_end && sval.contains('e') {
        if sval.ends_with('%') {
            sval="0.00%".to_string();
        }else{
            sval = "0.00".to_string();
        }
        return (sval, 0);
    }
    if let Some(dt) = dt {
        if dt == &DataType::String {
            let spaces = count_leading_spaces(&sval);
            return (sval, spaces);
        }
    }
    (sval, 0)
}
pub fn json_value_format(fmt: Option<&str>, value: &Value) -> String {
    match value {
        Value::Number(n) => {
            if let Some(fval) = n.as_f64() {
                format_float(fmt, fval)
            } else {
                n.to_string()
            }
        }
        _ => to_string(value).to_string(),
    }
}
pub fn format_json_value(dt: Option<&DataType>, fmt: Option<&str>, value: &Value) -> String {
    if dt.is_none() {
        return to_string(value).to_string();
    }
    if value.is_null() {
        return "".to_string();
    }
    let dt = dt.unwrap();
    match dt {
        DataType::Bool => {
            let val = value.as_bool().unwrap_or(false);
            if val {
                "是".to_string()
            } else {
                "否".to_string()
            }
        }
        DataType::Float => {
            if let Some(val) = value.as_f64() {
                format_float(fmt, val)
            } else {
                to_string(value).to_string()
            }
        }
        DataType::Date => {
            if let Some(v) = value.as_str() {
                if v.is_empty() {
                    return "".to_string();
                }
                let date = v.parse::<NaiveDate>().unwrap();
                let format = fmt.unwrap_or("%Y-%m-%d");
                let date_str = date.format(format).to_string();
                format!("{}", date_str)
            } else {
                return "".to_string();
            }
        }
        DataType::Datetime => {
            if let Some(v) = value.as_str() {
                if v.is_empty() {
                    return "".to_string();
                }
                // 更安全的日期时间解析
                match NaiveDateTime::parse_from_str(v, "%Y-%m-%d %H:%M:%S") {
                    Ok(date) => {
                        let format = fmt.unwrap_or("%Y-%m-%d %H:%M:%S");
                        date.format(format).to_string()
                    },
                    Err(_) => {
                        // 尝试其他常见格式
                        if let Ok(date) = NaiveDate::parse_from_str(v, "%Y-%m-%d") {
                            let format = fmt.unwrap_or("%Y-%m-%d");
                            date.format(format).to_string()
                        } else {
                            // 如果所有解析都失败，记录错误并返回空字符串
                            log::error!("Failed to parse datetime string: {}", v);
                            "".to_string()
                        }
                    }
                }
            } else {
                "".to_string()
            }
        }
        DataType::String => {
            let mut sval = to_string(value).to_string();
            if sval.ends_with("%") {
                return sval; // 如果是百分比格式，直接返回
            }
            if let Some(fmt) = fmt {
                if !fmt.is_empty() {
                    if let Ok(fval) = sval.parse::<f64>() {
                        sval = format_float(Some(fmt), fval);
                    }
                }
            }
            sval
        }
        _ => {
            if let Some(val) = value.as_i64() {
                val.to_string()
            } else {
                to_string(value).to_string()
            }
        }
    }
}

fn to_string(val: &Value) -> Cow<str> {
    match val {
        Value::Null | Value::Array(_) | Value::Object(_) => Cow::Borrowed(""),
        Value::Bool(bv) => Cow::Borrowed(if *bv { "是" } else { "否" }),
        Value::Number(nv) => Cow::Owned(nv.to_string()),
        Value::String(sv) => Cow::Borrowed(sv),
    }
}

pub fn format_float(fmt: Option<&str>, val: f64) -> String {
    let fmt_str = format!("[{}]", fmt.unwrap_or(".2n"));
    let mut f: Formatter = (&fmt_str)
        .parse()
        .or_else(|err| {
            log::error!("值:{val}格式化:{fmt_str}出错:{}", err);
            Err(err)
        })
        .unwrap();
    let sv = f.fmt2(val).to_owned();
    sv
}
fn count_leading_spaces(s: &str) -> usize {
    let mut count = 0;
    for c in s.chars() {
        if c == ' ' {
            count += 1;
        } else {
            break;
        }
    }
    count
}
